<template>
  <view>
    <!-- my-tabs是一个通用的组件
		   a.  可在父组件中定制 my-tabs 样式 
		   b.  可在父组件中设置展示数据 
		   c.  可在父组件中设置默认的激活项 
		   d.  由此分析，定义处以下代码： 
		 -->
    <view class="tab-container">
      <view class="tab-box">
        <scroll-view
          scroll-x
          class="scroll-view"
          scroll-with-animation
          :scrollLeft="scrollLeft"
        >
          <view class="scroll-content">
            <view class="tab-item-box">
              <block v-for="(item, index) in tabData" :key="index">
                <view
                  :id="'_tab_' + index"
                  class="tab-item"
                  :class="{ 'tab-item-active': activeIndex === index }"
                  @click="onTabClick(index)"
                  :style="{
                    color:
                      activeIndex === index
                        ? defaultConfig.activeTextColor
                        : defaultConfig.textColor,
                  }"
                  >{{ item.label || item }}</view
                >
                <!-- 滑块 -->
                <view
                  class="underLine"
                  :style="{
                    transform: `translateX(${slider.left}px)`,
                    width: defaultConfig.underLineWidth + 'px',
                    height: defaultConfig.underLineHeight + 'px',
                    backgroundColor: defaultConfig.underLineColor + 'px',
                  }"
                ></view>
              </block>
            </view>
          </view>
        </scroll-view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  name: "my-tabs",
  data() {
    return {
      // tabList 内部维护的数据对象，为每个item单独维护一个 slider的滑块对象
      tabList: [],
      // 当前激活下的index
      activeIndex: -1,
      // 滑块
      // 1.确定滚动的时机 ：点击tabs时
      // 2.计算滑块滚动的距离
      slider: {
        // 滑块距离左侧
        left: 0,
      },
      // scrollView的横向滚动条位置
      scrollLeft: 0,
      // 默认配置
      defaultConfig: {
        // 默认的字体颜色
        textColor: "#333333",
        // 高亮字体颜色
        activeTextColor: "#f94d2a",
        // 下划线宽度 px
        underLineWidth: 24,
        // 下划线高度 px
        underLineHeight: 2,
        // 下划线颜色
        underLineColor: "#f94d2a",
      },
    };
  },
  props: {
    config: {
      type: Object,
      // 如果default是复杂数据类型，需要通过返回值形式执行默认值
      default: () => {},
    },
    tabData: {
      type: Array,
      default: () => [],
    },
    defaultIndex: {
      type: Number,
      default: 0,
    },
  },
  methods: {
    /**
     * 更新tab的宽度
     */
    updateTabWidth() {
      // tabItem的宽度 、 tabItem的 left ， 为tabList中的每个item维护一个slider对象
      let data = this.tabList;
      if (data.length === 0) return;
      // 拿到渲染之后的dom
      // 获取dom的固定写法
      const query = uni.createSelectorQuery().in(this);
      data.forEach((item, index) => {
        // 获取dom 固定写法
        query
          .select("#_tab_" + index)
          .boundingClientRect((res) => {
            // res就是拿到的dom
            // 为数据对象的每个item都维护一个 _slider对象
            item._slider = {
              // left = tabItem.left + ((tabItem.width - slider.width) / 2)
              left:
                res.left + (res.width - this.defaultConfig.underLineWidth) / 2,
            };
            // 运算完成后 计算滑块的位置
            if (data.length - 1 === index) {
              this.tabToIndex();
            }
          })
          .exec();
      });
    },
    /**
     * tabs-item点击事件
     */
    onTabClick(index) {
      this.activeIndex = index;
      this.tabToIndex();
      this.$emit("tabClick", index);
    },
    /**
     * 计算滑块滚动位置
     */
    tabToIndex() {
      if (this.tabList.length === 0) return;
      const index = this.activeIndex;
      // 计算滑块滚动 === slider.left
      this.slider = {
        // tabItem宽度 tabItem的left slider的width
        // left = tabItem.left + ((tabItem.width - slider.width) / 2)
        left: this.tabList[index]._slider.left,
      };
      // 控制scrollView进行横向的滚动
      this.scrollLeft = this.activeIndex * this.defaultConfig.underLineWidth;
    },
  },
  watch: {
    config: {
      // handler 发生变化时，回调的方法
      handler(val) {
        this.defaultConfig = { ...this.defaultConfig, ...val };
      },
      immediate: true,
    },
    tabData: {
      // handler 发生变化时，回调的方法
      handler(val) {
        this.tabList = val;
        // 维护tabList中每个item，为dom渲染完成之后
        // $nextTick虽然支持 但是有兼容性问题
        setTimeout(() => {
          this.updateTabWidth();
        }, 0);
      },
      immediate: true,
    },
    defaultIndex: {
      // handler 发生变化时，回调的方法
      handler(val) {
        this.activeIndex = val;
        // 重新计算滑块位置
        this.tabToIndex();
      },
      immediate: true,
    },
  },
};
</script>

<style lang="scss" scoped>
.tab-container {
  font-size: 14px;
  height: 45px;
  line-height: 45px;
  background-color: #fff;
  .tab-box {
    width: 100%;
    height: 45px;
    display: flex;
    position: relative;
    .scroll-view {
      white-space: nowrap;
      width: 100%;
      height: 100%;
      box-sizing: border-box;
      .scroll-content {
        width: 100%;
        height: 100%;
        position: relative;
        .tab-item-box {
          height: 100%;
          .tab-item {
            height: 100%;
            display: inline-block;
            text-align: center;
            padding: 0 15px;
            position: relative;
            color: #333;

            &-active {
              color: #f94d2a;
            }
          }
          .underLine {
            height: 2px;
            width: 25px;
            background-color: #f01414;
            border-radius: 3px;
            transition: 0.5s;
            position: absolute;
            bottom: 0;
          }
        }
      }
    }
  }
}
/* #ifdef H5 */
/deep/.uni-scroll-view::-webkit-scrollbar {
  display: none;
}

/deep/.uni-scroll-view {
  scrollbar-width: none;
}
/* #endif */
</style>
